package com.cy.module;

import com.cy.ext.plugin.route.ControllerBind;
import com.cy.model.Account;
import com.cy.model.Batch;
import com.cy.model.DeviceSales;
import com.cy.model.ProductOfOutput;
import com.cy.model.ProductOutput;
import com.cy.model.Shift;
import com.google.common.collect.Lists;
import com.jfinal.aop.Before;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.activerecord.tx.Tx;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

@ControllerBind(controllerKey = "/clmp/productOutput")
public class ProductOutputController extends WebApiController {

    @Override
    public void index() {
        ProductOutput productOutput = getModel(ProductOutput.class);
        int page = getParaToInt("pageIndex");
        int pageSize = getParaToInt("limit");
        productOutput.put("start_time", StringUtils.isBlank(getPara("start_time")) ? null : getPara("start_time"));
        productOutput.put("end_time", StringUtils.isBlank(getPara("end_time")) ? null : getPara("end_time"));
        productOutput.put("sn", StringUtils.isBlank(getPara("sn")) ? null : getPara("sn"));
        Page<ProductOutput> productOutputPage = ProductOutput.dao.paginate(page, pageSize, "po.*, a.account AS operator_name, COUNT(poo.id) AS count", productOutput);
        renderBuiPage(productOutputPage, 200);
    }

    @Before(Tx.class)
    @Override
    public void update() {
        Long id = getParaToLong();
        ProductOutput tempProductOutput = getModel(ProductOutput.class);
        ProductOutput productOutput = ProductOutput.dao.findById(id);
        productOutput.cover(tempProductOutput);
        productOutput.update();

        String snsStr = getPara("sns");
        List<String> sns = Lists.newArrayList(StringUtils.split(snsStr, ","));
        List<ProductOfOutput> originalRecords = ProductOfOutput.dao.findByOutputId(id);

        //排除相同元素不做修改
        for (Iterator<ProductOfOutput> originalRecordsIt = originalRecords.listIterator(); originalRecordsIt.hasNext();){
            ProductOfOutput originalRecord = originalRecordsIt.next();
            for(Iterator<String> snsIt = sns.listIterator(); snsIt.hasNext();){
                String sn = snsIt.next();
                if (originalRecord.getSn().equals(sn)){
                    originalRecordsIt.remove();
                    snsIt.remove();
                    break;
                }
            }
        }

        List<String> originalRecordIds = new ArrayList<>(originalRecords.size());
        List<String> originalRecordSns = new ArrayList<>(originalRecords.size());
        for (ProductOfOutput poo : originalRecords){
            originalRecordIds.add(String.valueOf(poo.getId()));
            originalRecordSns.add(poo.getSn());
        }

        try {
            //删除原有多余的产品
            if (originalRecordIds.size() > 0){
                ProductOfOutput.dao.deleteBatch("id", originalRecordIds.toArray());
                DeviceSales.dao.deleteBatch("sn", originalRecordSns.toArray());
            }
            //新增不存在的产品
            for (String sn : sns){
                new ProductOfOutput().setSn(sn).setOutputId(id).save();
            }
            postSave(sns);
            renderSuccess();
        } catch (Exception e){
            e.printStackTrace();
            renderFail();
        }
    }

    @Override
    public void save() {
        ProductOutput productOutput = getModel(ProductOutput.class);
        if (ProductOutput.dao.findByExpressNum(productOutput.getExpressNum()) != null){
            renderFail("快递单已存在");
            return;
        }
        Account loginAccount = getLoginAccount();
        productOutput.setOperatorId(loginAccount.getAccountId());
        productOutput.setOutputTime(new Date());
        try {
            productOutput.save();
            String snsStr = getPara("sns");
            if (StringUtils.isBlank(snsStr)){
                renderFail("不能为空");
                return;
            }
            StringBuilder msg = new StringBuilder();
            String[] sns = snsStr.indexOf(",") != -1 ? StringUtils.split(snsStr, ",") : StringUtils.split(snsStr, "\r\n");

            List<ProductOfOutput> products = new ArrayList<>(sns.length);
            for (String sn : sns){
                try {
                    if (StringUtils.isBlank(sn))
                        continue;
                    sn = sn.trim();
                    int index = sn.indexOf("SN:");
                    if (index == 0){//以SN开头
                        String tempSn = sn.substring(index + 3);
                        if (!tempSn.matches("\\d{9}")){
                            msg.append(sn).append("格式不正确<br>");
                            continue;
                        }
                        sn = tempSn;
                    } else if (index == -1){//不以SN开头
                        if (!sn.matches("\\d{9}")){
                            msg.append(sn).append("格式不正确<br>");
                            continue;
                        }
                    } else {
                        msg.append(sn).append("格式不正确<br>");
                        continue;
                    }

                    String batchNum = sn.substring(0, 5);
                    String serialNum = sn.substring(5);
                    Batch batch = Batch.dao.findByBatchNum(batchNum);
                    if (batch == null){
                        msg.append(sn).append("批次号不存在<br>");
                        continue;
                    }
                    Shift shift = batch.getShiftBySerialNum(serialNum);
                    if (shift == null){
                        msg.append(sn).append("序列号不存在<br>");
                        continue;
                    }

                    ProductOfOutput productOfOutput = ProductOfOutput.dao.findBySn(sn);
                    if (productOfOutput != null){
                        msg.append(sn).append("此产品已出库，无法再出库<br>");
                        continue;
                    }

                    DeviceSales lastDs = DeviceSales.dao.findLastBySn(sn);
                    if (lastDs != null){
                        msg.append(sn).append("此产品已销售，无法再出库<br>");
                        continue;
                    }

                    ProductOfOutput po = new ProductOfOutput();
                    po.setOutputId(productOutput.getId());
                    po.setSn(sn);
                    products.add(po);
                } catch (Exception e){
                    msg.append(sn).append("内部错误<br>");
                }
            }

            if(products.size() > 0){
                String column = "sn,output_id";
                int[] batch = Db.batch("INSERT INTO product_of_output (" + column + ") VALUES (?,?)", column, products, 50);
                msg.append("成功新增"+ batch.length +"条");
                postSave(products);
            }
            renderSuccess(msg.toString());
        } catch (Exception e) {
            e.printStackTrace();
            renderFail();
        }
    }

    @Before(Tx.class)
    @Override
    public void delete() {
        String[] ids = getPara().split("-");
        for (String id : ids) {
            ProductOutput.dao.deleteById(id);
            List<ProductOfOutput> poos = ProductOfOutput.dao.findByOutputId(Long.valueOf(id));
            ArrayList<String> sns = new ArrayList<>(poos.size());
            for (ProductOfOutput poo : poos){
                sns.add(poo.getSn());
            }
            DeviceSales.dao.deleteBatch("sn", sns.toArray());
            ProductOfOutput.dao.deleteBatch("output_id", id);
        }
        renderSuccess();
    }

    public void checkSn(){
        String sn = getPara("sn");
        if (StringUtils.isBlank(sn)){
            renderFail("sn为空");
            return;
        }
        sn = sn.trim();
        if (!sn.matches("\\d{9}")){
            renderFail("格式不正确");
            return;
        }

        String batchNum = sn.substring(0, 5);
        Batch batchNumEntry = Batch.dao.findByBatchNum(batchNum);
        if (batchNumEntry == null){
            renderFail("批次号不存在");
            return;
        }
        String serialNum = sn.substring(5);
        Shift shift = batchNumEntry.getShiftBySerialNum(serialNum);
        if (shift == null){
            renderFail("序列号不存在");
            return;
        }

        ProductOfOutput productOfOutput = ProductOfOutput.dao.findBySn(sn);
        if (productOfOutput != null){
            renderFail("此产品已出库，无法再出库");
            return;
        }

        DeviceSales lastDs = DeviceSales.dao.findLastBySn(sn);
        if (lastDs != null){
            renderFail("此产品已销售，无法再出库");
            return;
        }
        renderSuccess();
    }

    /*
    出库后销售
     */
    protected int postSave(List<?> poos){
        if (poos.size() == 0)
            return 0;
        boolean isString = poos.get(0) instanceof String;
        List<DeviceSales> dss = new ArrayList<>(poos.size());
        for (Object poo : poos){
            DeviceSales ds = new DeviceSales();
            ds.setSn(isString ? (String) poo : ((ProductOfOutput) poo).getSn());
            ds.setUserId(0L);
            ds.setSalesTime(new Date());
            dss.add(ds);
        }
        String columns = "user_id,sn,sales_time";
        return Db.batch("INSERT INTO device_sales("+ columns +") VALUES (?,?,?)", columns, dss, 50).length;
    }


    public void getSnByRecord(){
        Long recordId = getParaToLong("recordId");
        renderJson(ProductOfOutput.dao.findByOutputId(recordId));
    }

}